package org.thunms.framework.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

public class DaoSupport<T> implements Dao<T> {

	protected Class<T> entityClass;

	@SuppressWarnings("unchecked")
	public DaoSupport() {
		Type genType = getClass().getGenericSuperclass();
		if (genType instanceof ParameterizedType) {
			Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
			entityClass = (Class<T>) params[0];
		}

	}

	@Autowired
	protected HibernateTemplate HibernateTemplate;

	@Override
	public void delete(T entity) {
		this.HibernateTemplate.delete(entity);
	}
	@Override
	public void save(T entity) {
		this.HibernateTemplate.save(entity);
		
	}
	@SuppressWarnings("unchecked")
	@Override
	public List<T> query(String queryString) {
		return this.HibernateTemplate.find(queryString);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> query(String queryString, Object value) {
		return this.HibernateTemplate.find(queryString, value);
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<T> query(String queryString, Object... values) {
		return this.HibernateTemplate.find(queryString, values);
	}

	@Override
	public T get(Serializable id) {
		return this.HibernateTemplate.get(entityClass, id);
	}

	@Override
	public void saveOrUpdate(T entity) {
		this.HibernateTemplate.saveOrUpdate(entity);
	}

	@Override
	public void update(T entity) {
		this.HibernateTemplate.update(entity);
	}

	@Override
	public List<T> query(final String hql, final Integer page, final Integer rows, final List<Object> param) {
		return this.HibernateTemplate.execute(new HibernateCallback<List<T>>() {
			@SuppressWarnings("unchecked")
			@Override
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.createQuery(hql);
				if (param != null && param.size() > 0) {
					for (int i = 0; i < param.size(); i++) {
						q.setParameter(i, param.get(i));
					}
				}
				if (page != null) {
					q.setFirstResult((page - 1) * rows).setMaxResults(rows);
				}
				if (rows != null) {
					q.setMaxResults(rows);
				}
				return q.list();
			}

		});
	}

	@Override
	public List<T> query(final String hql, final Integer page, final Integer rows, final Object... param) {
		return this.HibernateTemplate.execute(new HibernateCallback<List<T>>() {

			@SuppressWarnings("unchecked")
			@Override
			public List<T> doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = session.createQuery(hql);
				if (param != null && param.length > 0) {
					for (int i = 0; i < param.length; i++) {
						q.setParameter(i, param[i]);
					}
				}
				if (page != null) {
					q.setFirstResult((page - 1) * rows).setMaxResults(rows);
				}
				if (rows != null) {
					q.setMaxResults(rows);
				}
				return q.list();
			}
		});
	}

	@Override
	public Long count(final String hql, final Object... param) {
		return this.HibernateTemplate.execute(new HibernateCallback<Long>() {

			@Override
			public Long doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = null;
				if (hql.indexOf("count(") > 0) {
					q = session.createQuery(hql);
				} else {
					q = session.createQuery(" select count(*) " + hql);
				}
				if (param != null && param.length > 0) {
					for (int i = 0; i < param.length; i++) {
						q.setParameter(i, param[i]);
					}
				}
				Object o = q.uniqueResult();
				if (o != null) {
					return Long.parseLong(String.valueOf(o));
				}
				return Long.valueOf(0);
			}
		});
	}

	@Override
	public Long count(final String hql, final List<Object> param) {
		return this.HibernateTemplate.execute(new HibernateCallback<Long>() {
			@Override
			public Long doInHibernate(Session session) throws HibernateException, SQLException {
				Query q = null;
				if (hql.indexOf("count(") > 0) {
					q = session.createQuery(hql);
				} else {
					q = session.createQuery(" select count(*) " + hql);
				}
				if (param != null && param.size() > 0) {
					for (int i = 0; i < param.size(); i++) {
						q.setParameter(i, param.get(i));
					}
				}
				Object o = q.uniqueResult();
				if (o != null) {
					return Long.parseLong(String.valueOf(o));
				}
				return Long.valueOf(0);
			}
		});
	}

	

}
